﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Security.Cryptography;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace ExamSharedClasses
{
    /// <summary>
    /// (k) Hier werden, statisch, allgemein nützliche Methoden gelagert.
    /// </summary>
    public static class Tools
    {

        // ALGORITHMS
        /// <summary>
        /// (k) Diese Methode macht einen 40-Zeichen SHA1-Hash
        /// aus dem übergebenem String
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static string GenerateSHA1Hash(string text)
        {
            byte[] buffer = new ASCIIEncoding().GetBytes(text);
            SHA1CryptoServiceProvider cryptoTransformSHA1 = new SHA1CryptoServiceProvider();
            return BitConverter.ToString(cryptoTransformSHA1.ComputeHash(buffer)).Replace("-", "");
        }
        /// <summary>
        /// (k) gibt die auflistung der in einer zahl enthaltenen Zweierpotenzen zurück
        /// z.b. aus (int)15 wird "1, 2, 4, 8"
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        public static string EnumerateLeftToRightPositionsOfPowersOfTwo( int number ) {
            StringBuilder sb = new StringBuilder( );
            if (number <= 0) {
                sb.Append("-");        
            } else {
                for (int i = 0; i < 10; i++) {
                    if ((number & (1 << i)) == (1 << i))
                        sb.Append((i + 1).ToString() + ", ");
                }
            }
            return sb.ToString().Trim().Trim(',');
        }
        /// <summary>
        /// (k) Bricht einen großen int-Wert an Sekunden in Minuten und Restsekunden auf..
        /// </summary>
        /// <param name="secs"></param>
        /// <returns></returns>
        public static string GetReadableTimeStringOfValueWithSeconds( int secs ) {
            StringBuilder sb = new StringBuilder();

            if (secs <= 0) {
                sb.Append("abgelaufen");
            } else {
                int min = secs / 60;
                if (min == 1) {
                    sb.Append("1 Minute ");
                } else if (min > 1) {
                    sb.Append(min + " Minuten ");
                }
                int sek = secs % 60;
                if (sek == 1) {
                    sb.Append("1 Sekunde ");
                } else if (sek > 1) {
                    sb.Append(sek + " Sekunden ");
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// (k) Um Strings besser vergleichen zu können werden die Zeichen
        /// ` ' ´ - , . {Leerzeichen}
        /// entfernt und die UpperCase-Variante der Zeichen erzwungen.
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static string GetRidOfCertainCharacters( string text ) {
            if ( text != null )
                return text.Replace( "`", "" ).Replace( "´", "" ).Replace( "'", "" ).Replace( " ", "" ).Replace( "-", "" ).Replace( ",", "" ).Replace( ".", "" ).Trim().ToUpper();
            else
                return "";
        }


        // FILE
        /// <summary>
        /// (k) soll nur einen String an eine vorgegebene Datei hängen können
        /// interessant ist hier der einsatz des using-schlüsselworts
        /// </summary>
        /// <param name="text"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static bool AppendStringToFile(string text, string fileName)
        {   
            try
            {
                using (System.IO.StreamWriter file = new System.IO.StreamWriter(fileName, true))
                {
                    file.WriteLine(text);
                }
            }
            catch 
            {
                return false;
            }
            return true;    
        }
        /// <summary>
        /// (k) Diese Methode soll das schnelle absepeichern eines Objektes ermöglichen
        /// </summary>
        /// <param name="o"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static bool SerializeObjectToFile( object o, string fileName ) {
            Stream stream = new FileStream( fileName, FileMode.OpenOrCreate, FileAccess.Write );
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize( stream, o );
            stream.Close();
            return true;
        }
        /// <summary>
        /// (k) Diese Methode versucht, ein Objekt aus einer angegebenen Datei zu gewinnen
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static object DeserializeObjectFromFile( string fileName ) {
            Stream stream = new FileStream( fileName, FileMode.Open, FileAccess.Read );
            BinaryFormatter bf = new BinaryFormatter();
            object o = bf.Deserialize( stream );
            stream.Close();
            return o;
        }

        // MYSQL
        /// <summary>
        /// (k) Schafft einen String, den die Datenbank als gültigen Datetime-Typen akzeptiert.
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static string ToMySQLDate( DateTime date ) {
            return date.Year + "-" + date.Month + "-" + date.Day + " " + date.Hour + ":" + date.Minute + ":" + date.Second;
        }
 
    }
}
